#include "onvif.nsmap"
#include "onvif.h"

static int listen_port = 8080; //default
static unsigned char server_ip[4] = {192,168,0,7};
static unsigned char macaddr[6]={0x01,0x02,0x03,0x04,0x05,0x06};
static const char *dev_type = "tdn:NetworkVideoTransmitter";
static const char *dev_scopes[] = {
	"onvif://www.onvif.org/type/NetworkVideoTransmitter",
	NULL
};

int init_configs(void)
{
	init_mediaservice_configs();
	
	return 0;
}

void exit_configs(int sig)
{
	DBG("catch signal:%d\n", sig);
	exit_mediaservice_configs();
	exit(0);
}

// get XAddr value
char *get_ipaddr(void)
{
	static char ip[IPv4_LEN];

	bzero(ip,IPv4_LEN);
	snprintf(ip, IPv4_LEN,
			"%03d.%03d.%1d.%03d", 
			server_ip[0], server_ip[1], server_ip[2], server_ip[3]);
	return ip;
}

char *get_xaddrs(void)
{
	static char xaddrs[XADDR_LEN];

	bzero(xaddrs,XADDR_LEN);
	snprintf(xaddrs, XADDR_LEN,
			"http://%03d.%03d.%1d.%03d:%d/onvif/device_service", 
			server_ip[0], server_ip[1], server_ip[2], server_ip[3], listen_port);
	return xaddrs;
}

char *get_uuid(void)
{
	static char uuid[UUID_LEN];

	bzero(uuid,UUID_LEN);
	// build uuid using MAC address.
	snprintf(uuid,UUID_LEN,
			"urn:uuid:2419d68a-2dd2-21b2-a205-%02X%02X%02X%02X%02X%02X",
			macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
	return uuid;
}

int process_specific_fault(struct soap *soap, const char *fault_code[])
{
	int i,len;
	struct SOAP_ENV__Code* psubcode;

	if(strcmp(fault_code[FAULT_CODE],"env:Receiver")==0)
	{
		soap_receiver_fault_subcode(soap,fault_code[PARENT_SUBCODE],fault_code[FAULT_REASON],NULL);
	}
	else if(strcmp(fault_code[FAULT_CODE],"env:Sender")==0)
	{
		soap_sender_fault_subcode(soap,fault_code[PARENT_SUBCODE],fault_code[FAULT_REASON],NULL);
	}

	// use soap1.2
	// fill service specific sub code.
	psubcode = soap->fault->SOAP_ENV__Code->SOAP_ENV__Subcode;
	for(i=SPEC_SUBCODE;fault_code[i]!=NULL;i++)
	{
		len = strlen(fault_code[i]);
		psubcode->SOAP_ENV__Subcode = (struct SOAP_ENV__Code*)soap_malloc(soap,sizeof(struct SOAP_ENV__Code));
		psubcode = psubcode->SOAP_ENV__Subcode;
		psubcode->SOAP_ENV__Value = (char *)soap_malloc(soap,sizeof(len+1));
		strcpy(psubcode->SOAP_ENV__Value, fault_code[i]);
		psubcode->SOAP_ENV__Subcode = NULL;
	}

	return 0;
}

static int create_server_socket_udp(void)
{
    int server_udp;
	unsigned char one = 1;
	int sock_opt = 1;
	
	//server_udp = socket(PF_INET, SOCK_DGRAM, 0);
    server_udp = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (server_udp == -1) {
        perror("unable to create socket:");
    }

    /* reuse socket addr */
    if ((setsockopt(server_udp, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,
                    sizeof (sock_opt))) == -1) {
        perror("setsockopt:");
    }
    if ((setsockopt(server_udp, IPPROTO_IP, IP_MULTICAST_LOOP,
                       &one, sizeof (unsigned char))) == -1) {
        perror("setsockopt:");
    }

	struct ip_mreq mreq;
	mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
	mreq.imr_interface.s_addr = htonl(INADDR_ANY);

	if(setsockopt(server_udp,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))==-1){
		perror("memberchip: ");
	}

    return server_udp;
}

static int bind_server_udp1(int server_s)
{
	struct sockaddr_in local_addr;
	if(server_s < 0) return -1;
	memset(&local_addr,0,sizeof(local_addr));
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	local_addr.sin_port = htons(3702);
	return bind(server_s,(struct sockaddr*)&local_addr,sizeof(local_addr));
}


void *probe_thread(void *arg)
{
	int server_udp = create_server_socket_udp();
	int ret = bind_server_udp1(server_udp);
	if(ret < 0) 
	{
		fprintf(stderr,"server_udp = %d,ret = %d\n",server_udp,ret);
		return NULL;
	}
	
	//struct soap *soap = soap_new1(argc > 1 ? atoi(argv[1]) : 0);
	struct soap *soap = soap_new();
	while(1)
	{
		soap_init1(soap, SOAP_IO_UDP);
		soap->master = server_udp;
		soap->socket = server_udp;
		soap->errmode = 0;
		soap->bind_flags = 1;

		//fprintf(stderr,"soap server start...\n");
		ret = soap_serve(soap);
		//fprintf(stderr, "soap_server ret = %d\n",ret);
		soap_destroy(soap);
		soap_end(soap);
	}
	soap_free(soap);
	return NULL;
}


int main(int argc, char **argv)
{
	struct soap* soap = soap_new();
	int m,s,ret;
	pthread_t tid;

	signal(SIGINT, exit_configs);
	signal(SIGPIPE, exit_configs);
	signal(SIGTERM, exit_configs);
	init_configs();

	pthread_create(&tid,NULL,probe_thread,NULL);
	if (argc >= 2)
	{
		if(atoi(argv[1]) > 0 ) 
			listen_port = atoi(argv[1]);
	}
	m = soap_bind(soap, NULL, listen_port, 100);
	DBG("soap master socket: %d\n",m);
	if (soap_valid_socket(m))
	{
		while( s = soap_accept(soap))
		{
			//DBG("soap client socket: %d\n",s);
			if(soap_valid_socket(s))
			{	
				ret = soap_serve(soap);
				if(ret != SOAP_OK)
				{
					soap_print_fault(soap,stderr);
					printf("soap->error:%d\n",soap->error);
				}
				soap_destroy(soap);
				soap_end(soap);
			}
			else
				soap_print_fault(soap,stderr);
		}
	}
	else
	{
		soap_print_fault(soap,stderr);
	}

	soap_free(soap);

	exit_configs(0);

	return 0;
}


/** Auto-test server operation SOAP_ENV__Fault */
int SOAP_ENV__Fault(struct soap *soap, char *faultcode, char *faultstring, char *faultactor, struct SOAP_ENV__Detail *detail, struct SOAP_ENV__Code *SOAP_ENV__Code, struct SOAP_ENV__Reason *SOAP_ENV__Reason, char *SOAP_ENV__Node, char *SOAP_ENV__Role, struct SOAP_ENV__Detail *SOAP_ENV__Detail)
{	
	char fault_info[128];
	struct SOAP_ENV__Code *p = SOAP_ENV__Code;
	int len = 0;

	if(p != NULL)
	{
		len = snprintf(fault_info,128,"%s",p->SOAP_ENV__Value);
		for(p = p->SOAP_ENV__Subcode;p;p = p->SOAP_ENV__Subcode)
		{
			len += snprintf(fault_info+len,128-len,"|%s",p->SOAP_ENV__Value);
		}
	}
	if(SOAP_ENV__Reason != NULL)
	{
		len += snprintf(fault_info+len,128-len,"::%s\n",SOAP_ENV__Reason->SOAP_ENV__Text);
	}
	if(len > 0)
		fprintf(stderr,"%s",fault_info);

	return SOAP_OK;
}


/** Auto-test server operation __wsdd__Hello */
int __wsdd__Hello(struct soap *soap, struct wsdd__HelloType *wsdd__Hello)
{	
	/* ws-discovery: one-way hello, a client may implement it.*/
	return SOAP_OK;
}

/*     ws-discovery,page 14.
 * A Target Service MUST send a one-way Hello when any of the following occur:
 * • It joins a network. This may be detected through low-level mechanisms, such
 * 	 as wireless beacons, or through a change in IP connectivity on one or more of
 *   its network interfaces.
 * • Its metadata changes. 
 * The Hello MUST be sent multicast using the assignments listed in Section 2.4 Protocol Assignments.
 *
 */
// supported to be called.
// the caller need to fill 'wsdd_hello' struct-variable members by ws-discovery
// spec.
static int send_wsdd_Hello(struct soap *soap, struct wsdd__HelloType *wsdd__Hello)
{	
	struct __wsdd__Hello soap_tmp___wsdd__Hello;
	const char *soap_action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Hello";

	soap->encodingStyle = NULL;
	soap_tmp___wsdd__Hello.wsdd__Hello = wsdd__Hello;
	soap_begin(soap);
	soap_set_version(soap, 2); /* SOAP1.2 */
	soap_serializeheader(soap);
	soap_serialize___wsdd__Hello(soap, &soap_tmp___wsdd__Hello);
	if (soap_begin_count(soap))
		return soap->error;
	if (soap->mode & SOAP_IO_LENGTH)
	{	if (soap_envelope_begin_out(soap)
		 || soap_putheader(soap)
		 || soap_body_begin_out(soap)
		 || soap_put___wsdd__Hello(soap, &soap_tmp___wsdd__Hello, "-wsdd:Hello", NULL)
		 || soap_body_end_out(soap)
		 || soap_envelope_end_out(soap))
			 return soap->error;
	}
	if (soap_end_count(soap))
		return soap->error;
	if (soap_connect(soap, soap_url(soap, "http://", NULL), soap_action)
	 || soap_envelope_begin_out(soap)
	 || soap_putheader(soap)
	 || soap_body_begin_out(soap)
	 || soap_put___wsdd__Hello(soap, &soap_tmp___wsdd__Hello, "-wsdd:Hello", NULL)
	 || soap_body_end_out(soap)
	 || soap_envelope_end_out(soap)
	 || soap_end_send(soap))
		return soap_closesock(soap);
	return SOAP_OK;
}

/*   ws-discovery,page 17
 * A Target Service SHOULD send a one-way Bye message when it is preparing to
 * leave a network. (A Target Service MUST NOT send a Bye message when its
 * metadata changes.)
 * The Bye MUST be sent multicast using the assignments listed in Section 2.4
 * Protocol Assignments.
 * A Target Service MAY send the Bye without waiting for a timer to elapse.
 *
 */
// supported to be called.
// the caller need to fill 'wsdd_hello' struct-variable members by ws-discovery
// spec.
static int send_wsdd_Bye(struct soap *soap, struct wsdd__ByeType *wsdd__Bye)
{	
	struct __wsdd__Bye soap_tmp___wsdd__Bye;
	const char *soap_action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Bye";

	soap->encodingStyle = NULL;
	soap_tmp___wsdd__Bye.wsdd__Bye = wsdd__Bye;
	soap_begin(soap);
	soap_set_version(soap, 2); /* SOAP1.2 */
	soap_serializeheader(soap);
	soap_serialize___wsdd__Bye(soap, &soap_tmp___wsdd__Bye);
	if (soap_begin_count(soap))
		return soap->error;
	if (soap->mode & SOAP_IO_LENGTH)
	{	if (soap_envelope_begin_out(soap)
		 || soap_putheader(soap)
		 || soap_body_begin_out(soap)
		 || soap_put___wsdd__Bye(soap, &soap_tmp___wsdd__Bye, "-wsdd:Bye", NULL)
		 || soap_body_end_out(soap)
		 || soap_envelope_end_out(soap))
			 return soap->error;
	}
	if (soap_end_count(soap))
		return soap->error;
	if (soap_connect(soap, soap_url(soap, "http://", NULL), soap_action)
	 || soap_envelope_begin_out(soap)
	 || soap_putheader(soap)
	 || soap_body_begin_out(soap)
	 || soap_put___wsdd__Bye(soap, &soap_tmp___wsdd__Bye, "-wsdd:Bye", NULL)
	 || soap_body_end_out(soap)
	 || soap_envelope_end_out(soap)
	 || soap_end_send(soap))
		return soap_closesock(soap);
	return SOAP_OK;
}

/** Auto-test server operation __wsdd__Bye */
int __wsdd__Bye(struct soap *soap, struct wsdd__ByeType *wsdd__Bye)
{	
	/* do nothing */
	return SOAP_OK;
}

static int send_wsdd_ProbeMatches(struct soap *soap, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
{	
	INFO(stderr);	
	struct __wsdd__ProbeMatches soap_tmp___wsdd__ProbeMatches;
	//const char *soap_action = "http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/ProbeMatches";
	const char *soap_action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches";

	soap->encodingStyle = NULL;
	soap_tmp___wsdd__ProbeMatches.wsdd__ProbeMatches = wsdd__ProbeMatches;
	soap->header->wsa__Action = (char *)soap_malloc(soap, sizeof(char)*256);
	memcpy(soap->header->wsa__Action, soap_action,256);
	soap_begin(soap);
	soap_serializeheader(soap);
	soap_serialize___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches);
	if (soap_begin_count(soap))
		return soap->error;
	if (soap->mode & SOAP_IO_LENGTH)
	{	if (soap_envelope_begin_out(soap)
		 || soap_putheader(soap)
		 || soap_body_begin_out(soap)
		 || soap_put___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches, "-wsdd:ProbeMatches", NULL)
		 || soap_body_end_out(soap)
		 || soap_envelope_end_out(soap))
			 return soap->error;
	}
	if (soap_end_count(soap))
		return soap->error;
	if (soap_connect(soap, soap_url(soap, "http://", NULL), soap_action)
	 || soap_envelope_begin_out(soap)
	 || soap_putheader(soap)
	 || soap_body_begin_out(soap)
	 || soap_put___wsdd__ProbeMatches(soap, &soap_tmp___wsdd__ProbeMatches, "-wsdd:ProbeMatches", NULL)
	 || soap_body_end_out(soap)
	 || soap_envelope_end_out(soap)
	 || soap_end_send(soap))
		return soap_closesock(soap);
	return SOAP_OK;
}

/** Auto-test server operation __wsdd__Probe */
int __wsdd__Probe(struct soap *soap, struct wsdd__ProbeType *wsdd__Probe)
{	
	INFO(stderr);	

	wsdd__ProbeMatchesType ProbeMatches;
	ProbeMatches.ProbeMatch = (struct wsdd__ProbeMatchType *)soap_malloc(soap, sizeof(struct wsdd__ProbeMatchType));
	ProbeMatches.ProbeMatch->XAddrs = (char *)soap_malloc(soap, sizeof(char) * XADDR_LEN);
	ProbeMatches.ProbeMatch->Types = (char *)soap_malloc(soap, sizeof(char) * XADDR_LEN);
	ProbeMatches.ProbeMatch->Scopes = (struct wsdd__ScopesType*)soap_malloc(soap,sizeof(struct wsdd__ScopesType));
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceProperties = (struct wsa__ReferencePropertiesType*)soap_malloc(soap,sizeof(struct wsa__ReferencePropertiesType));
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceParameters = (struct wsa__ReferenceParametersType*)soap_malloc(soap,sizeof(struct wsa__ReferenceParametersType));
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName = (struct wsa__ServiceNameType*)soap_malloc(soap,sizeof(struct wsa__ServiceNameType));
	ProbeMatches.ProbeMatch->wsa__EndpointReference.PortType = (char **)soap_malloc(soap, sizeof(char *) * INFO_LEN);
	ProbeMatches.ProbeMatch->wsa__EndpointReference.__any = (char **)soap_malloc(soap, sizeof(char*) * INFO_LEN);
	ProbeMatches.ProbeMatch->wsa__EndpointReference.__anyAttribute = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);
	ProbeMatches.ProbeMatch->wsa__EndpointReference.Address = (char *)soap_malloc(soap, sizeof(char) * XADDR_LEN);

	ProbeMatches.__sizeProbeMatch = 1;
	ProbeMatches.ProbeMatch->Scopes->__item =(char *)soap_malloc(soap, XADDR_LEN);
	memset(ProbeMatches.ProbeMatch->Scopes->__item,0,sizeof(ProbeMatches.ProbeMatch->Scopes->__item));	

	//Scopes MUST BE
	strcat(ProbeMatches.ProbeMatch->Scopes->__item, dev_scopes[0]);

	ProbeMatches.ProbeMatch->Scopes->MatchBy = NULL;
	strcpy(ProbeMatches.ProbeMatch->XAddrs, get_xaddrs());
	//strcpy(ProbeMatches.ProbeMatch->Types, wsdd__Probe->Types);
	strcpy(ProbeMatches.ProbeMatch->Types, dev_type);
	//DBG("wsdd__Probe->Types=%s\n",wsdd__Probe->Types);
	ProbeMatches.ProbeMatch->MetadataVersion = 1;
	//ws-discovery规定 为可选项
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceProperties->__size = 0;
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceProperties->__any = NULL;
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceParameters->__size = 0;
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceParameters->__any = NULL;
	
	ProbeMatches.ProbeMatch->wsa__EndpointReference.PortType[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);
	//ws-discovery规定 为可选项
	strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.PortType[0], "ttl");
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName->__item = NULL;
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName->PortName = NULL;
	ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName->__anyAttribute = NULL;
	ProbeMatches.ProbeMatch->wsa__EndpointReference.__any[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);
	strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.__any[0], "Any");
	strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.__anyAttribute, "Attribute");
	ProbeMatches.ProbeMatch->wsa__EndpointReference.__size = 0;
	strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.Address, get_uuid());

	/*注释的部分为可选，注释掉onvif test也能发现ws-d*/
	//soap->header->wsa__To = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
	//soap->header->wsa__Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches";
	soap->header->wsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));
	//it's here
	soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID;
	soap->header->wsa__RelatesTo->RelationshipType = NULL;
	soap->header->wsa__RelatesTo->__anyAttribute = NULL;
	soap->header->wsa__MessageID =(char *)soap_malloc(soap, sizeof(char) * UUID_LEN);
	strcpy(soap->header->wsa__MessageID,get_uuid()+4);

	send_wsdd_ProbeMatches(soap, &ProbeMatches);
	return SOAP_OK;
}


/** Auto-test server operation __wsdd__ProbeMatches */
int __wsdd__ProbeMatches(struct soap *soap, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
{	
	return SOAP_OK;
}

/*
 * If a Target Service matches a Resolve, the Target Service MUST respond with a
 * Resolve Match message. Comparison MUST be done per WS-Addressing Section 2.4
 * Endpoint Reference Comparison [WS-Addressing]. If the Target Service receives
 * Page 24 of 42
 * more than one copy of the Resolve, it SHOULD respond only once.
 *
 */
static int send_wsdd_ResolveMatches(struct soap *soap, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches)
{	
	struct __wsdd__ResolveMatches soap_tmp___wsdd__ResolveMatches;
	const char *soap_action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/ResolveMatches";

	soap->encodingStyle = NULL;
	soap_tmp___wsdd__ResolveMatches.wsdd__ResolveMatches = wsdd__ResolveMatches;
	soap_begin(soap);
	soap_set_version(soap, 2); /* SOAP1.2 */
	soap_serializeheader(soap);
	soap_serialize___wsdd__ResolveMatches(soap, &soap_tmp___wsdd__ResolveMatches);
	if (soap_begin_count(soap))
		return soap->error;
	if (soap->mode & SOAP_IO_LENGTH)
	{	if (soap_envelope_begin_out(soap)
		 || soap_putheader(soap)
		 || soap_body_begin_out(soap)
		 || soap_put___wsdd__ResolveMatches(soap, &soap_tmp___wsdd__ResolveMatches, "-wsdd:ResolveMatches", NULL)
		 || soap_body_end_out(soap)
		 || soap_envelope_end_out(soap))
			 return soap->error;
	}
	if (soap_end_count(soap))
		return soap->error;
	if (soap_connect(soap, soap_url(soap, "http://", NULL), soap_action)
	 || soap_envelope_begin_out(soap)
	 || soap_putheader(soap)
	 || soap_body_begin_out(soap)
	 || soap_put___wsdd__ResolveMatches(soap, &soap_tmp___wsdd__ResolveMatches, "-wsdd:ResolveMatches", NULL)
	 || soap_body_end_out(soap)
	 || soap_envelope_end_out(soap)
	 || soap_end_send(soap))
		return soap_closesock(soap);
	return SOAP_OK;
}

/** Auto-test server operation __wsdd__Resolve */
int __wsdd__Resolve(struct soap *soap, struct wsdd__ResolveType *wsdd__Resolve)
{	
	wsdd__ResolveMatchesType ResolveMatch;
	ResolveMatch.ResolveMatch = (struct wsdd__ResolveMatchType *)soap_malloc(soap, sizeof(struct wsdd__ResolveMatchType));
	ResolveMatch.ResolveMatch->XAddrs = (char *)soap_malloc(soap, sizeof(char) * XADDR_LEN);
	ResolveMatch.ResolveMatch->Types = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);
	ResolveMatch.ResolveMatch->Scopes = (struct wsdd__ScopesType*)soap_malloc(soap,sizeof(struct wsdd__ScopesType));
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ReferenceProperties = (struct wsa__ReferencePropertiesType*)soap_malloc(soap,sizeof(struct wsa__ReferencePropertiesType));
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ReferenceParameters = (struct wsa__ReferenceParametersType*)soap_malloc(soap,sizeof(struct wsa__ReferenceParametersType));
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ServiceName = (struct wsa__ServiceNameType*)soap_malloc(soap,sizeof(struct wsa__ServiceNameType));
	ResolveMatch.ResolveMatch->wsa__EndpointReference.PortType = (char **)soap_malloc(soap, sizeof(char *) * INFO_LEN);
	ResolveMatch.ResolveMatch->wsa__EndpointReference.__any = (char **)soap_malloc(soap, sizeof(char*) * INFO_LEN);
	ResolveMatch.ResolveMatch->wsa__EndpointReference.__anyAttribute = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);
	ResolveMatch.ResolveMatch->wsa__EndpointReference.Address = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);

	//Scopes MUST BE
	ResolveMatch.ResolveMatch->Scopes->__item =(char *)soap_malloc(soap, XADDR_LEN);
	memset(ResolveMatch.ResolveMatch->Scopes->__item,0,sizeof(ResolveMatch.ResolveMatch->Scopes->__item));	
	strcat(ResolveMatch.ResolveMatch->Scopes->__item, dev_scopes[0]);
	ResolveMatch.ResolveMatch->Scopes->MatchBy = NULL;
	strcpy(ResolveMatch.ResolveMatch->XAddrs, get_xaddrs());
	//strcpy(ResolveMatch.ResolveMatch->Types, wsdd__Probe->Types);
	strcpy(ResolveMatch.ResolveMatch->Types, dev_type);
	//DBG("wsdd__Probe->Types=%s\n",wsdd__Probe->Types);
	ResolveMatch.ResolveMatch->MetadataVersion = 1;
	//ws-discovery规定 为可选项
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ReferenceProperties->__size = 0;
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ReferenceProperties->__any = NULL;
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ReferenceParameters->__size = 0;
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ReferenceParameters->__any = NULL;
	
	ResolveMatch.ResolveMatch->wsa__EndpointReference.PortType[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);
	//ws-discovery规定 为可选项
	strcpy(ResolveMatch.ResolveMatch->wsa__EndpointReference.PortType[0], "ttl");
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ServiceName->__item = NULL;
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ServiceName->PortName = NULL;
	ResolveMatch.ResolveMatch->wsa__EndpointReference.ServiceName->__anyAttribute = NULL;
	ResolveMatch.ResolveMatch->wsa__EndpointReference.__any[0] = (char *)soap_malloc(soap, sizeof(char) * INFO_LEN);
	strcpy(ResolveMatch.ResolveMatch->wsa__EndpointReference.__any[0], "Any");
	strcpy(ResolveMatch.ResolveMatch->wsa__EndpointReference.__anyAttribute, "Attribute");
	ResolveMatch.ResolveMatch->wsa__EndpointReference.__size = 0;
	strcpy(ResolveMatch.ResolveMatch->wsa__EndpointReference.Address, get_uuid());

	/*注释的部分为可选，注释掉onvif test也能发现ws-d*/
	//soap->header->wsa__To = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
	//soap->header->wsa__Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/ResolveMatch";
	soap->header->wsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));
	//it's here
	soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID;
	soap->header->wsa__RelatesTo->RelationshipType = NULL;
	soap->header->wsa__RelatesTo->__anyAttribute = NULL;

	soap->header->wsa__MessageID =(char *)soap_malloc(soap, sizeof(char) * UUID_LEN);
	strcpy(soap->header->wsa__MessageID,get_uuid()+4);

	send_wsdd_ResolveMatches(soap, &ResolveMatch);

	return SOAP_OK;
}


/** Auto-test server operation __wsdd__ResolveMatches */
int __wsdd__ResolveMatches(struct soap *soap, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches)
{	
	return SOAP_OK;
}


/** Auto-test server operation __tdn__Hello */
int __tdn__Hello(struct soap *soap, struct wsdd__HelloType tdn__Hello, struct wsdd__ResolveType *tdn__HelloResponse)
{	
	/* Return incomplete response with default data values */
	return SOAP_OK;
}


/** Auto-test server operation __tdn__Bye */
int __tdn__Bye(struct soap *soap, struct wsdd__ByeType tdn__Bye, struct wsdd__ResolveType *tdn__ByeResponse)
{	
	/* Return incomplete response with default data values */
	return SOAP_OK;
}


/** Auto-test server operation __tdn__Probe */
int __tdn__Probe(struct soap *soap, struct wsdd__ProbeType tdn__Probe, struct wsdd__ProbeMatchesType *tdn__ProbeResponse)
{	
	/* Return incomplete response with default data values */
	return SOAP_OK;
}
